package com.example.lib_base.base.vm

import android.annotation.SuppressLint
import android.app.Application
import android.net.ParseException
import androidx.annotation.StringRes
import androidx.lifecycle.*
import com.example.lib_base.base.http.ApiResponse
import com.example.lib_base.base.http.HttpError
import com.example.lib_base.base.extensions.toast
import com.google.gson.JsonParseException
import kotlinx.coroutines.*
import org.json.JSONException
import retrofit2.HttpException
import java.io.InterruptedIOException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException

abstract class BaseViewModel : ViewModel(), ViewBehavior, ViewModelLifecycle {

    /**
     * api返回数据 经过过滤 转换后交由具体实现类使用
     */
    protected abstract fun <T : ApiResponse<*>> serverResponseObj(
        bean: T,
        code: Int,
        message: String
    )

    /**
     * 在ViewModel中，我们可能会使用到Context，在ViewModel中并不适合持有Activity/Fragment的引用
     * 这里使用Application
     */
    @SuppressLint("StaticFieldLeak")
    lateinit var application: Application

    /**
     * Lifecycle持有者
     * 实现该接口的类持有生命周期(Lifecycle对象)，该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。
     */
    private lateinit var lifcycleOwner: LifecycleOwner

    /**
     * 在主线程中执行一个协程
     */
    protected fun launchOnUI(block: suspend CoroutineScope.() -> Unit): Job {
        return viewModelScope.launch(Dispatchers.Main) { block() }
    }

    /**
     * 在IO线程中执行一个协程
     */
    protected fun launchOnIO(block: suspend CoroutineScope.() -> Unit): Job {
        return viewModelScope.launch(Dispatchers.IO) { block() }
    }

    /**
     * 访问服务器
     * 通过此函数访问服务器 接口的 正确/异常 将经过过滤
     */
    protected suspend fun <T : Any> accessServer(block: suspend () -> ApiResponse<T>) {
        try {
            var bean = block.invoke()
            if (bean.isSuccess()) {
                serverResponseObj(bean = bean, code = bean.code, message = bean.message)
            } else {
                serverError(code = bean.code,message = bean.message,type = bean)
            }
        } catch (e: Throwable) {
            networkError(e,ApiResponse(code = -1,message = "",data = ""))
        } finally {

        }
    }

    protected suspend fun <T : Any, B : Any> accessServer(
        type: B,
        block: suspend () -> ApiResponse<T>
    ) {
        try {
            var bean = block.invoke()
            if (bean.isSuccess()) {
                println("--------------------- 成功")
                serverResponseObj(bean = bean, code = bean.code, message = bean.message)
            } else {
                println("--------------------- 失败")
                serverError(code = bean.code,message = bean.message,type = type)
;            }
        } catch (e: Throwable) {
            println("--------------------- 异常$e ")
            networkError(e,type)

        } finally {
            println("--------------------- 结束")
        }
    }

    /**
     * 网络错误 404 超时等
     */
    open fun <B : Any> networkError(e: Throwable, type: B) {

        when (e) {
            is UnknownHostException -> {
                "网络连接失败".toast()
//                showToast("网络连接失败")
            }
            is SocketTimeoutException -> {
                "连接超时".toast()
//                showToast("连接超时")
            }
            else -> {
                "服务器连接失败".toast()
//                showToast("服务器连接失败")
            }

        }
    }

    /**
     * 与服务器约定的返回码为false时
     */
    open fun <B : Any>serverError(code: Int , message: String, type: B ) {
//        showToast(message)
        message.toast()
    }


    /**
     * 解析网络请求异常
     */
    protected fun parseException(e: Throwable): HttpError {
        return when (e) {
            is HttpException -> HttpError.BAD_NETWORK
            is ConnectException, is UnknownHostException -> HttpError.CONNECT_ERROR
            is InterruptedIOException -> HttpError.CONNECT_TIMEOUT
            is JsonParseException, is JSONException, is ParseException, is ClassCastException -> HttpError.PARSE_ERROR
            is CancellationException -> HttpError.CANCEL_REQUEST
            else -> HttpError.UNKNOWN
        }
    }


    protected fun showToast(msg: String, duration: Int? = null) {
        val map = HashMap<String, Any>().apply {
            put(
                FlyBaseConstants.FLY_TOAST_KEY_CONTENT_TYPE,
                FlyBaseConstants.FLY_TOAST_CONTENT_TYPE_STR
            )
            put(FlyBaseConstants.FLY_TOAST_KEY_CONTENT, msg)
            if (duration != null) {
                put(FlyBaseConstants.FLY_TOAST_KEY_DURATION, duration)
            }
        }
        showToast(map)
    }

    protected fun showToast(@StringRes resId: Int, duration: Int? = null) {
        val map = HashMap<String, Any>().apply {
            put(
                FlyBaseConstants.FLY_TOAST_KEY_CONTENT_TYPE,
                FlyBaseConstants.FLY_TOAST_CONTENT_TYPE_RESID
            )
            put(FlyBaseConstants.FLY_TOAST_KEY_CONTENT, resId)
            if (duration != null) {
                put(FlyBaseConstants.FLY_TOAST_KEY_DURATION, duration)
            }
        }
        showToast(map)
    }

    protected fun backPress() {
        backPress(null)
    }

    protected fun finishPage() {
        finishPage(null)
    }

    companion object {
        @JvmStatic
        fun <T : BaseViewModel> createViewModelFactory(viewModel: T): ViewModelProvider.Factory {
            return ViewModelFactory(viewModel)
        }
    }

    /**
     * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 页面的常用操作 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
     */
    /**
     * loading视图显示Event
     */
    var _loadingEvent = MutableLiveData<Boolean>()
        private set

    /**
     * 无数据视图显示Event
     */
    var _emptyPageEvent = MutableLiveData<Boolean>()
        private set

    /**
     * toast提示Event
     */
    var _toastEvent = MutableLiveData<Map<String, *>>()
        private set

    /**
     * 不带参数的页面跳转Event
     */
    var _pageNavigationEvent = MutableLiveData<Any>()
        private set

    /**
     * 点击系统返回键Event
     */
    var _backPressEvent = MutableLiveData<Any?>()
        private set

    /**
     * 关闭页面Event
     */
    var _finishPageEvent = MutableLiveData<Any?>()
        private set

    override fun showLoadingUI(isShow: Boolean) {
        _loadingEvent.postValue(isShow)
    }

    override fun showEmptyUI(isShow: Boolean) {
        _emptyPageEvent.postValue(isShow)
    }

    override fun showToast(map: Map<String, *>) {
        _toastEvent.postValue(map)
    }

    override fun navigate(page: Any) {
        _pageNavigationEvent.postValue(page)
    }

    override fun backPress(arg: Any?) {
        _backPressEvent.postValue(arg)
    }

    override fun finishPage(arg: Any?) {
        _finishPageEvent.postValue(arg)
    }

    /**
     * ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 页面的常用操作 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
     */

    /**
     * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ViewModel感知生命周期接口 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
     */

    override fun onAny(owner: LifecycleOwner, event: Lifecycle.Event) {
        this.lifcycleOwner = owner
    }

    override fun onCreate() {
    }

    override fun onStart() {
    }

    override fun onResume() {
    }

    override fun onPause() {
    }

    override fun onStop() {
    }

    override fun onDestroy() {
    }
    /**
     * ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ViewModel感知生命周期接口 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
     */
}

/**
 * 创建ViewModel的工厂，以此方法创建的ViewModel，可在构造函数中传参
 * val vm = LoginViewModel(loginRepository)
viewModel = ViewModelProvider(this,BaseViewModel.createViewModelFactory(vm)).get(vm:class.java)
 */
class ViewModelFactory(val viewModel: BaseViewModel) : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return viewModel as T
    }
}